package con.shake;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.widget.Toast;
import android.content.Context;
import java.lang.UnsupportedOperationException;

public class ShakeListener {
	private static final int FORCE_THRESHOLD = 350;
	private static final int TIME_THRESHOLD = 100;
	private static final int SHAKE_TIMEOUT = 500;
	private static final int SHAKE_DURATION = 1000;
	private static final int SHAKE_COUNT = 3;
	
	public static final int SHAKE_DIRECTION_X = 0;
	public static final int SHAKE_DIRECTION_Y = 1;
	public static final int SHAKE_DIRECTION_Z = 2;
	
	private SensorManager mSensorMgr;
	private Sensor sensor;
	private float mLastX = -1.0f, mLastY = -1.0f, mLastZ = -1.0f;
	private long mLastTime;
	private OnShakeListener mShakeListener;
	private Context mContext;
	private int mShakeCount = 0;
	private long mLastShake;
	private long mLastForce;

	private SensorEventListener mySensorEventListener = new SensorEventListener() {
		public void onSensorChanged(SensorEvent event) {
			int sensor = event.sensor.getType();
			float[] values = event.values;
			if (sensor != Sensor.TYPE_ACCELEROMETER) {
				return;
			}
			long now = System.currentTimeMillis();

			if ((now - mLastForce) > SHAKE_TIMEOUT) {
				mShakeCount = 0;
			}

			if ((now - mLastTime) > TIME_THRESHOLD) {
				long diff = now - mLastTime;
	
				float dx = Math.abs(values[SensorManager.DATA_X]-mLastX);
				float dy = Math.abs(values[SensorManager.DATA_Y]-mLastY);
				float dz = Math.abs(values[SensorManager.DATA_Z]-mLastZ);
				float speed = dx/diff * 10000;
				int shakeDirection = SHAKE_DIRECTION_X;
				if(dy>dx && dy>dz){
					shakeDirection = SHAKE_DIRECTION_Y;
					speed = dy/diff * 10000;;
				}else if(dz>dx && dz>dy){
					shakeDirection = SHAKE_DIRECTION_Z;
					speed = dz/diff * 10000;;
				}				
//				speed = Math.abs(values[SensorManager.DATA_X]
//						+ values[SensorManager.DATA_Y]
//						+ values[SensorManager.DATA_Z] - mLastX - mLastY
//						- mLastZ)
//						/ diff * 10000;
				if (speed > FORCE_THRESHOLD) {
					if ((++mShakeCount >= SHAKE_COUNT)
							&& (now - mLastShake > SHAKE_DURATION)) {
						mLastShake = now;
						mShakeCount = 0;
						if (mShakeListener != null) {
							mShakeListener.onShake(shakeDirection);
						}
					}
					mLastForce = now;
				}
				mLastTime = now;
				mLastX = values[SensorManager.DATA_X];
				mLastY = values[SensorManager.DATA_Y];
				mLastZ = values[SensorManager.DATA_Z];
			}
		}

		public void onAccuracyChanged(Sensor s, int arg1) {
		}
	};

	public interface OnShakeListener {
		public void onShake(int direction);
	}

	public ShakeListener(Context context) {
		mContext = context;

		resume();
	}

	public void setOnShakeListener(OnShakeListener listener) {
		mShakeListener = listener;
	}

	public void resume() {
		mSensorMgr = (SensorManager) mContext
				.getSystemService(Context.SENSOR_SERVICE);
		if (mSensorMgr == null) {
			throw new UnsupportedOperationException("Sensors not supported");
		}
		sensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
		if (sensor != null) {
			// sensorService.registerListener(mySensorEventListener, sensor,
			// SensorManager.SENSOR_DELAY_NORMAL);
			mSensorMgr.registerListener(mySensorEventListener, sensor,
					SensorManager.SENSOR_DELAY_GAME);
		} else {
			Toast.makeText(mContext, "ORIENTATION Sensor not found",
					Toast.LENGTH_LONG).show();
		}
		// boolean supported = mSensorMgr.registerListener(this,
		// SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME);
		// if (!supported) {
		// mSensorMgr.unregisterListener(this,
		// SensorManager.SENSOR_ACCELEROMETER);
		// throw new
		// UnsupportedOperationException("Accelerometer not supported");
		// }
	}

	public void destroy() {
		// if (mSensorMgr != null) {
		// mSensorMgr.unregisterListener(this,
		// SensorManager.SENSOR_ACCELEROMETER);
		// mSensorMgr = null;
		// }
		if (sensor != null) {
			mSensorMgr.unregisterListener(mySensorEventListener);
		}
	}
}